package org.durandj.ystream.server.message;

import java.nio.ByteBuffer;

/**
 * A message that lets a message handler know that something happened.
 * Each message is given a priority to denote how important this message
 * is and can carry specific information about the event that triggered
 * the message. Finally messages do store the sender of the message.
 * 
 * @author durandj
 * @version 1.0
 *
 */
public class Message implements Comparable<Message>
{
	// TODO: This could probably be automated a bit.
	
	/**
	 * Represents the priority of a message. A message can be of high,
	 * medium, or low importance.
	 * 
	 * @author durandj
	 * @version 1.0
	 *
	 */
	public static enum Priority
	{
		HIGH,
		MEDIUM,
		LOW
	}
	
	/**
	 * The priority of the message.
	 */
	private Priority priority;
	
	/**
	 * The message ID.
	 */
	private MessageID id;
	
	/**
	 * The sender of the message.
	 */
	private Object sender;
	
	/**
	 * The contents of the message.
	 */
	private ByteBuffer contents;
	
	/**
	 * Creates a message with the given information.
	 * 
	 * @param priority - the priority of the message
	 * @param id - the message ID
	 * @param sender - the sender of the message
	 */
	public Message(Priority priority, MessageID id, Object sender)
	{
		this(priority, id, sender, null);
	}
	
	/**
	 * Creates a message with the given information.
	 * 
	 * @param priority - the priority of the message
	 * @param id - the message ID
	 * @param sender - the sender of the message
	 * @param contents - the contents of the message
	 */
	public Message(Priority priority, MessageID id, Object sender, ByteBuffer contents)
	{
		if(priority == null)
			throw new NullPointerException("Must give the priority of the message.");
		
		if(id == null)
			throw new NullPointerException("Must give the ID of the message.");
		
		if(sender == null)
			throw new NullPointerException("Must give the sender of the message.");
		
		this.priority = priority;
		this.id = id;
		this.sender = sender;
		this.contents = contents;
		
		// Because the contents really shouldn't be changed after this lets rewind them.
		if(this.contents != null)
			this.contents.rewind();
	}
	
	/**
	 * Gets the message priority.
	 * 
	 * @return the priority
	 */
	public Priority getPriority()
	{
		return priority;
	}

	/**
	 * Gets the message ID.
	 * 
	 * @return the id
	 */
	public MessageID getID()
	{
		return id;
	}

	/**
	 * Gets the sender of the message.
	 * 
	 * @return the sender
	 */
	public Object getSender()
	{
		return sender;
	}

	/**
	 * Gets the contents of the message.
	 * 
	 * @return the contents
	 */
	public ByteBuffer getContents()
	{
		return contents;
	}

	/* (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(Message obj)
	{
		if(obj == null)
			throw new NullPointerException("Must give an object to compare to.");
		
		switch(obj.getPriority())
		{
		case HIGH:
			if(priority == Priority.HIGH)
				return 0;
			else
				return 1;
			
		case MEDIUM:
			if(priority == Priority.HIGH)
				return -1;
			else if(priority == Priority.MEDIUM)
				return 0;
			else
				return 1;
			
		case LOW:
			if(priority == Priority.LOW)
				return 0;
			else
				return -1;
		}
		
		// This will never be reached...
		return 0;
	}
}
